package jEDF.FFT;

import java.awt.*;
import java.awt.event.*;
import java.text.*;

import javax.swing.*;

import jEDF.JEDF.*;

/**
 *
 * <p>Titre : jEDF</p>
 * <p>Description : Java European Data Format Viewer and Analyser</p>
 * <p>Author : Nizar Kerkeni</p>
 * <p>Copyright : Copyright (c) 2003-2006</p>
 * <p>Version 2.0</p>
 */
public class FFTAnalysisDialog extends JDialog {

    private Polysomnograph polysomnograph = null;
    private JLabel jlMode = new JLabel();
    private JRadioButton jrbSleepBandsView = new JRadioButton();
    private JRadioButton jrbOneHzView = new JRadioButton();
    private ButtonGroup buttonGroup = new ButtonGroup();
    private JEDFGraph graph = null;
    private int startSecond = 0;
    private int duration = 0;
    private double startPosition = 0;
    private double endPosition = 0;
    private JTabbedPane jTabbedPane = new JTabbedPane();
    private JLabel statusBar = new JLabel();
    private JPanel fftDrawingArea = new JPanel() {

        protected void paintComponent(Graphics arg0) {
            super.paintComponent(arg0);

            setBackground(Color.WHITE);

            if (graph == null) {
                return;
            }

            Graphics2D g2d = (Graphics2D) arg0;
            drawData(g2d);
        }

        private void drawData(Graphics2D g) {
            double[] data = null;

            if (jrbOneHzView.isSelected()) {
                data = graph.getSignal().getFourierTransformedDataBy1Hz(
                        startSecond, duration, startPosition, endPosition);
            } else if (jrbSleepBandsView.isSelected()) {
                data = graph.getSignal().getFourierTransformedDataBySleepBands(
                        startSecond, duration, startPosition, endPosition);
            }

            double sum = 0.0;

            for (int i = 0; i < data.length; i++) {
                sum += data[i];
            }

            for (int i = 0; i < data.length; i++) {
                data[i] /= sum;
            }

            double width = SwingUtilities.calculateInnerArea(this,
                    new Rectangle()).getWidth();
            double height = SwingUtilities.calculateInnerArea(this,
                    new Rectangle()).getHeight();

            double coefWidth = width / (double) data.length;

            height -= drawCaptionPanel(g, coefWidth);

            Color originalColor = g.getColor();

            for (int i = 0; i < data.length; i++) {
                g.setColor(new Color(1f - (float) data[i], 0.5f, (float) data[i]));
                g.fillRect((int) Math.round(i * coefWidth),
                        (int) Math.round(height - (height * data[i])),
                        (int) Math.round(coefWidth),
                        (int) Math.round(height * data[i]));
            }

            g.setColor(originalColor);
        }

        private int centerString(Graphics2D g, String text, int coefWidth) {
            FontMetrics fontMetrics = g.getFontMetrics();
            int strWidth = fontMetrics.stringWidth(text);

            coefWidth -= strWidth;

            if (coefWidth <= 0) {
                return 0;
            }

            coefWidth /= 2;

            return coefWidth;
        }

        private int drawCaptionPanel(Graphics2D g, double coefWidth) {
            FontMetrics fontMetrics = g.getFontMetrics();
            double width = SwingUtilities.calculateInnerArea(this,
                    new Rectangle()).getWidth();
            double height = SwingUtilities.calculateInnerArea(this,
                    new Rectangle()).getHeight();

            Color originalColor = g.getColor();
            g.setColor(Color.BLACK);

            //          delta theta alpha sigma beta
            String[] labels = {"Delta", "Theta", "Alpha", "Sigma", "Beta"};

            if (jrbOneHzView.isSelected()) {
                for (int i = 0; (i * coefWidth) < width; i++) {
                    g.drawString("" + i,
                            centerString(g, "" + i, (int) coefWidth) +
                            (int) (i * coefWidth), (int) Math.round(height));
                }
            } else if (jrbSleepBandsView.isSelected()) {
                for (int i = 0; (i < labels.length) && ((i * coefWidth) < width);
                        i++) {
                    g.drawString(labels[i],
                            centerString(g, labels[i], (int) coefWidth) +
                            (int) (i * coefWidth),
                            (int) Math.round(height) - 3);
                }
            }
            g.setColor(originalColor);

            return fontMetrics.getHeight();
        }
    };
    private JPanel signalDrawingArea = new JPanel() {

        protected void paintComponent(Graphics arg0) {
            super.paintComponent(arg0);

            setBackground(Color.WHITE);

            if (graph == null) {
                return;
            }

            Graphics2D g2d = (Graphics2D) arg0;

            double height = SwingUtilities.calculateInnerArea(this,
                    new Rectangle()).getHeight();
            double width = SwingUtilities.calculateInnerArea(this,
                    new Rectangle()).getWidth();

            graph.draw(g2d, 0, width, height, startPosition, endPosition);
        }
    };

    public FFTAnalysisDialog(Polysomnograph polysomnograph) {
        this.polysomnograph = polysomnograph;

        setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);

        buttonGroup.add(jrbSleepBandsView);
        buttonGroup.add(jrbOneHzView);
        jrbSleepBandsView.setSelected(true);

        jrbSleepBandsView.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                fftDrawingArea.repaint();
            }
        });
        jrbOneHzView.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                fftDrawingArea.repaint();
            }
        });

        updateTexts();

        organize();
        pack();
        setLocationRelativeTo(null);
        setAlwaysOnTop(true);
    }

    public void repaint() {
        super.repaint();
        updateStatusBar();
    }

    private void organize() {
        JPanel northPanel = new JPanel();
        northPanel.add(jlMode);
        northPanel.add(jrbSleepBandsView);
        northPanel.add(jrbOneHzView);

        JPanel fftClientArea = new JPanel(new BorderLayout());
        fftClientArea.add(northPanel, BorderLayout.NORTH);
        fftClientArea.add(fftDrawingArea, BorderLayout.CENTER);

        fftDrawingArea.setPreferredSize(new Dimension(640, 240));

        jTabbedPane.add(JEDFMainWindow.getLocalizedString("FFT"), fftClientArea);
        jTabbedPane.add(JEDFMainWindow.getLocalizedString("Signal"), signalDrawingArea);

        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(jTabbedPane, BorderLayout.CENTER);
        getContentPane().add(statusBar, BorderLayout.SOUTH);
    }

    public void setDataSource(JEDFGraph graph, int startSecond, int duration,
            double startPosition, double endPosition) {
        this.graph = (JEDFGraph) graph.clone();
        this.startSecond = startSecond;
        this.duration = duration;
        this.startPosition = startPosition;
        this.endPosition = endPosition;

        if (isVisible()) {
            repaint();
        } else {
//            setVisible(true);
        }
    }

    public void updateTexts() {
        setTitle(JEDFMainWindow.getLocalizedString("FFT Analysis"));
        jrbOneHzView.setText("1 Hz");
        jrbSleepBandsView.setText(JEDFMainWindow.getLocalizedString("Sleep bands"));
        jlMode.setText(JEDFMainWindow.getLocalizedString("Visualization mode :"));
        updateStatusBar();
    }

    public void setVisible(boolean arg0) {
        arg0 = arg0 && (polysomnograph.getAllGraphs().length > 0);

        if (arg0) {
            updateTexts();
        }

        super.setVisible(arg0);
    }

    private void updateStatusBar() {
        if (graph == null) {
            return;
        }

        double samples = endPosition - startPosition;
        samples *= (double) duration;

        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);

        statusBar.setText(graph.getSignal().getLabel() + "      " +
                numberFormat.format(samples) + "s");
    }
}
